import { CloseCircleFilled, FileOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';

import { commonUploadApi } from '@/api/commonApi';
import { isImageUrl } from '@/utils';

import type { RequestBody } from 'alova';
import type { UploadFile, UploadProps } from 'antd';
import './index.scss';

export interface CustomUploadProps {
  // 基础属性
  value?: UploadFile[];
  onChange?: (fileList: UploadFile[]) => void;

  // 文件类型限制
  accept?: string;
  acceptTypes?: string[]; // 例如: ['image/jpeg', 'image/png', 'application/pdf']

  multiple?: boolean;
  maxCount?: number;
  maxSize?: number; // MB

  // 样式配置
  listType?: 'text' | 'picture' | 'picture-card' | 'picture-circle';
  showUploadList?: boolean | object;
  // 是否需要返回base64
  withBase64?: boolean;
  // 自定义文案
  uploadText?: string;
  placeholder?: string;

  // 其他配置
  disabled?: boolean;
  className?: string;
  style?: React.CSSProperties;
  uploadApi?: (data: RequestBody) => Promise<{ success: boolean; data?: string; message?: string }>;
}

const CustomUpload: React.FC<CustomUploadProps> = ({
  value = [],
  onChange,
  accept,
  acceptTypes = [],
  multiple = true,
  maxCount = 2,
  maxSize = 5, // 5MB
  listType = 'picture-card',
  showUploadList = true,
  uploadText = '点击上传',
  placeholder = '支持格式jpg、png、pdf，最多支持上传多个文件，单个容量不超过5M',
  disabled = false,
  className,
  style,
  uploadApi,
  withBase64,
}) => {
  const customRequest = async (
    options: Parameters<NonNullable<UploadProps['customRequest']>>[0]
  ) => {
    console.log('customRequest options:', options);
    const { file, onSuccess, onError } = options;

    const formData = new FormData();
    formData.append('file', file as File);

    try {
      let res: any;
      if (uploadApi) {
        res = await uploadApi(formData);
      } else {
        res = await commonUploadApi(formData);
      }

      console.log(res);
      const thumbUrl = await getBase64(file as File);

      if (res.success || res.url) {
        const fileObj = file as File & { uid: string };
        const newFile: UploadFile = {
          uid: fileObj.uid,
          type: fileObj.type,
          name: fileObj.name,
          originFileObj: fileObj as any, // 类型兼容性处理
          status: 'done',
          thumbUrl: thumbUrl,
          url: (res.data || res.url) as string, // 假设接口返回文件 URL
        };
        const uploadFile = {
          ...newFile,
        };
        if (!withBase64) {
          delete uploadFile.thumbUrl;
        }
        onSuccess?.(res);
        onChange?.([...(value || []), uploadFile]);
      } else {
        onError?.(new Error('上传失败'));
      }
    } catch (error) {
      onError?.(error as Error);
    }
  };
  // 获取文件的base64编码用于预览
  const getBase64 = (file: File): Promise<string> =>
    new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result as string);
      reader.onerror = error => reject(error);
    });

  // 上传前的校验
  const beforeUpload = (file: File) => {
    // 文件类型校验
    if (acceptTypes.length > 0 && !acceptTypes.includes(file.type)) {
      const allowedTypes = acceptTypes
        .map(type => {
          const parts = type.split('/');
          return parts[1] || parts[0];
        })
        .join('、');
      window.$message.error(`只支持上传 ${allowedTypes} 格式的文件`);
      return false;
    }

    // 文件大小校验
    const isLtMaxSize = file.size / 1024 / 1024 < maxSize;
    if (!isLtMaxSize) {
      window.$message.error(`文件大小不能超过 ${maxSize}MB`);
      return false;
    }

    return true;
  };

  // 自定义上传列表项
  const customItemRender = (originNode: React.ReactElement, file: UploadFile) => {
    const isImage = file.type?.startsWith('image/') || isImageUrl(file.url as string);
    // console.log('[ isImage ] >', file);
    if (listType === 'picture-card') {
      return (
        <div className="ant-upload-list-item-container relative upload-list-item-border">
          <div className="ant-upload-list-item-info h-full">
            {isImage ? (
              <AImage
                src={file.thumbUrl ?? file.url}
                alt={file.name}
                style={{ width: '100%', height: '100%', objectFit: 'cover' }}
              />
            ) : (
              <div className="ant-upload-list-item-thumbnail">
                <FileOutlined className="color-primary text-6" />
                <div style={{ fontSize: '12px', marginTop: '4px', textAlign: 'center' }}>
                  {file.name}
                </div>
              </div>
            )}
          </div>
          <div
            className="absolute top-0 right-0 upload-del-btn"
            onClick={() => {
              const newFileList = value.filter(item => item.uid !== file.uid);
              onChange?.(newFileList);
            }}
          >
            <CloseCircleFilled />
          </div>
          {file.status === 'uploading' && (
            <AProgress
              percent={file.percent}
              size="small"
              status="active"
              style={{ position: 'absolute', bottom: '8px', left: '8px', right: '8px' }}
            />
          )}
        </div>
      );
    }

    return originNode;
  };

  // 上传按钮
  const uploadButton = (
    <div>
      {listType === 'picture-card' ? (
        <div>
          <PlusOutlined />
          <div style={{ marginTop: 8 }}>{uploadText}</div>
        </div>
      ) : (
        <AButton icon={<UploadOutlined />} disabled={disabled}>
          {uploadText}
        </AButton>
      )}
    </div>
  );

  return (
    <div className={className} style={style}>
      <AUpload
        customRequest={customRequest}
        listType={listType}
        fileList={value}
        multiple={multiple}
        maxCount={maxCount}
        accept={accept ?? acceptTypes.join(',')}
        beforeUpload={beforeUpload}
        showUploadList={showUploadList}
        disabled={disabled}
        itemRender={customItemRender}
      >
        {value.length >= maxCount ? null : uploadButton}
      </AUpload>

      {placeholder && (
        <ATypography.Text
          type="secondary"
          style={{ fontSize: '12px', marginTop: '8px', display: 'block' }}
        >
          {placeholder}
        </ATypography.Text>
      )}
    </div>
  );
};

export default CustomUpload;
